package com.xyy.saas.payment.merchant.core.service;

import com.alibaba.fastjson.JSONObject;
import com.xyy.framework.redis.core.RedisClient;
import com.xyy.saas.payment.adpater.RouteManager;
import com.xyy.saas.payment.common.Constants;
import com.xyy.saas.payment.common.exception.PaymentException;
import com.xyy.saas.payment.cores.enums.*;
import com.xyy.saas.payment.cores.param.Pair;
import com.xyy.saas.payment.cores.vo.ResultVO;
import com.xyy.saas.payment.dao.model.ApplypayUserInfo;
import com.xyy.saas.payment.dao.model.OpenpayInfo;
import com.xyy.saas.payment.dao.model.PayAccount;
import com.xyy.saas.payment.dao.model.ThirdUserInfo;
import com.xyy.saas.payment.merchant.core.dto.CreateAllPayDto;
import com.xyy.saas.payment.merchant.core.dto.OpenPayDto;
import com.xyy.saas.payment.service.OpenpayInfoService;
import com.xyy.saas.payment.service.PayAccountService;
import com.xyy.saas.payment.service.ThirdUserInfoService;
import com.xyy.saas.payment.util.ApolloUtil;
import com.xyy.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import util.AESUtil;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class CreateAllPayService {
    @Resource
    private RedisClient redisClient;
    @Resource
    private ThirdUserInfoService thirdUserInfoService;
    @Resource
    private ApplypayUserInfoServiceV2 applypayUserInfoServiceV2;
    @Resource
    private PayAccountService payAccountService;
    @Resource
    private OpenpayInfoService openpayInfoService;
    @Resource
    private RouteManager routeManager;

    /**
     * 报件
     */
    public ResultVO<Boolean> createAllPay(CreateAllPayDto createAllPayDto) throws Exception {
        log.info("CreateAllPayService#createAllPay createAllPayDto：{}", JSONObject.toJSONString(createAllPayDto));

        // 0.防止连点value随便设置
        if(!StringUtil.isEmpty(redisClient.get("createAllPay" + createAllPayDto.getCompanyShortName()))) {
            return ResultVO.create(ResultCodeEnum.NOT_CONTINUOUS_CLICK);
        }

        redisClient.set("createAllPay" + createAllPayDto.getCompanyShortName(), "1", 5L);

        // 1.校验开户是否成功
        ThirdUserInfo thirdUserInfo = thirdUserInfoService.getThirdUserInfoByUserId(createAllPayDto.getUserId());

        if(thirdUserInfo == null || StringUtils.isBlank(thirdUserInfo.getThirdUserId()) ||
                Objects.equals(thirdUserInfo.getUserId(), thirdUserInfo.getThirdUserId()))
        {
            log.warn("CreateAllPayService#createAllPay APPLY_PAY_OPEN_ACCOUNT_FIRST：{}", JSONObject.toJSONString(createAllPayDto));
            return ResultVO.create(ResultCodeEnum.APPLY_PAY_OPEN_ACCOUNT_FIRST);
        }

        // 2.保存报件信息  userInfo.setBasicInfo(AESUtil.encrypt(JSONUtils.toJSON(userDto1), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        ApplypayUserInfo applypayUserInfo = new ApplypayUserInfo();
        applypayUserInfo.setAccountId(createAllPayDto.getUserId());
        applypayUserInfo.setThirdUserInfoId(thirdUserInfo.getId());
        applypayUserInfo.setBusinessLicenseInfo(AESUtil.encrypt(createAllPayDto.getBusinessLicenseInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setSettleInfo(AESUtil.encrypt(createAllPayDto.getSettleInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setContactInfo(AESUtil.encrypt(createAllPayDto.getContactInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setAccountInfo(AESUtil.encrypt(createAllPayDto.getAccountInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setLegalInfo(AESUtil.encrypt(createAllPayDto.getLegalInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setShareholderInfo(AESUtil.encrypt(createAllPayDto.getShareholderInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setBeneficiaryInfo(AESUtil.encrypt(createAllPayDto.getBeneficiaryInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setImgsInfo(AESUtil.encrypt(createAllPayDto.getimgsInfo(), ApolloUtil.getProperty(Constants.USER_INFO_KEY)));
        applypayUserInfo.setStatus(OpenPayStatusEnum.CREATE.getStatus());
        applypayUserInfo.setCallback(createAllPayDto.getCallback());
        applypayUserInfoServiceV2.insertOrUpdate(applypayUserInfo);

        // 3.进件
        try {
            // 添加开通支付功能参数
            List<OpenPayDto> openPayList = checkOpenPay(createAllPayDto.getUserId(), thirdUserInfo.getId(), createAllPayDto.getCompanyShortName());
            createAllPayDto.setOpenPayList(openPayList);
            routeManager.createAllPay(createAllPayDto);
            applypayUserInfoServiceV2.updateStatus(applypayUserInfo.getId(), OpenPayStatusEnum.OPENING);
        }
        catch(Exception ex) {
            String message = ex instanceof PaymentException ? ((PaymentException) ex).getErrMsg() : OpenPayStatusEnum.FAIL.getDesc();
            applypayUserInfoServiceV2.updateStatus(applypayUserInfo.getId(), OpenPayStatusEnum.FAIL.getStatus(), message);
            log.error("CreateAllPayService#createAllPay createAllPayDto error msg：" + ex.getMessage(), ex);
            return ResultVO.createError(message);
        }

        return ResultVO.createSuccess(Boolean.TRUE);
    }

    public List<OpenPayDto> checkOpenPay(String accountId, Long thirdUserInfoId, String companyShortName) throws Exception {
        log.info("OpenAccountServiceImpl#openPay begin accountId:{}, thirdUserInfoId:{}", accountId, thirdUserInfoId);

        // 1.检验是否已开通
        List<OpenpayInfo> openpayInfos = openpayInfoService.queryUserInfoByAccountId(accountId, thirdUserInfoId);

        if(!CollectionUtils.isEmpty(openpayInfos)) {
            return new ArrayList<>();
        }

        PayAccount payAccount =  payAccountService.getPayAccountByAccountId(accountId);
        List<OpenPayDto> result = new ArrayList<>();

        for(FBankPowerIdEnum powerIdEnum : FBankPowerIdEnum.values()) {
            try {
                // 2.保存开通支付功能信息
                OpenpayInfo openpayInfo = new OpenpayInfo();
                openpayInfo.setAccountId(accountId);
                openpayInfo.setThirdUserInfoId(thirdUserInfoId);
                openpayInfo.setPowerId(powerIdEnum.getPowerId());
                openpayInfo.setRate(powerIdEnum.getRate());
                openpayInfo.setStatus(OpenPayStatusEnum.CREATE.getStatus());
                openpayInfoService.insert(openpayInfo);

                // 3.开通支付功能参数组装
                OpenPayDto openPayDto = new OpenPayDto();
                openPayDto.setOpenPayChannel(powerIdEnum.getChannel());
                openPayDto.setPowerId(powerIdEnum.getPowerId());
                openPayDto.setRate(powerIdEnum.getRate());
                openPayDto.setMchntType(powerIdEnum.getMchntType());
                openPayDto.setMchntShortName(companyShortName);
                openPayDto.setMcc(powerIdEnum.getMcc());
                Pair pair = FBankPowerIdEnum.getAppIdInfo(payAccount.getBusinessIdType(), powerIdEnum);
                openPayDto.setSubAppid(pair.getKey());
                openPayDto.setAppletName(pair.getValue());

                // 4.更新开通状态
                openpayInfo.setStatus(OpenPayStatusEnum.OPENING.getStatus());
                openpayInfoService.updateByPrimaryKeySelective(openpayInfo);
                result.add(openPayDto);
            }
            catch(Exception ex) {
                log.error(ex.getMessage() + " ,accountId:" + accountId +
                        ", thirdUserInfoId:" + thirdUserInfoId + ", powerId:" + powerIdEnum.getPowerId() ,ex);
                throw ex;
            }
        }

        return result;
    }

}
